﻿using CleanArchitecture.Core.Helper;
using System;
using System.Collections.Generic;

namespace CleanArchitecture.Core.Configuration
{
    public enum FileType
    {
        /// <summary>
        /// Picture like jpeg,jpg,gif,png etc
        /// </summary>
        Image = 1,
        /// <summary>
        /// Audio like mp3,wav etc
        /// </summary>
        Audio = 2,
        /// <summary>
        /// text files like txt, doc, pdf etc
        /// </summary>
        TextFile = 3,
        /// <summary>
        /// Video file like mp4,webm etc
        /// </summary>
        Video = 4,
        /// <summary>
        /// File like rar, zip etc
        /// </summary>
        File = 5
    }
    /// <summary>
    /// Collection of MimeType Constants for using to avoid Typos
    /// If needed MimeTypes missing feel free to add
    /// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types
    /// </summary>
    public class MimeTypes
    {
        private static Dictionary<string, string> _supportUploadFile;

        #region 文件类型：压缩文件 FileType.File
        /// <summary>
        /// .bz
        /// </summary>
        public const string ApplicationBzip = "application/x-bzip;File;bz";
        /// <summary>
        /// .bz2
        /// </summary>
        public const string ApplicationBzip2 = "application/x-bzip;File;bz2";
        /// <summary>
        /// .rar
        /// </summary>
        public const string ApplicationRar = "application/x-rar-compressed;File;rar";
        /// <summary>
        /// .tar
        /// </summary>
        public const string ApplicationTar = "application/x-tar;File;tar";
        /// <summary>
        /// zip
        /// </summary>
        public const string ApplicationZip = "application/zip;File;zip";
        /// <summary>
        /// .7z
        /// </summary>
        public const string Application7Zip = "application/x-7z-compressed;File;7z";
        #endregion

        #region 文件类型：图片 FileType.Image
        /// <summary>
        /// .bmp
        /// </summary>
        public const string ImageBmp = "image/bmp;Image;bmp";

        /// <summary>
        /// .gif
        /// </summary>
        public const string ImageGif = "image/gif;Image;gif";

        /// <summary>
        /// .jpeg .jpg .jpe .jfif .pjpeg .pjp
        /// </summary>
        public const string ImageJpeg = "image/jpeg;Image;jpg";

        /// <summary>
        /// .png
        /// </summary>
        public const string ImagePng = "image/png;Image;png";

        /// <summary>
        /// .tif .tiff
        /// </summary>
        public const string ImageTiff = "image/tiff;Image;tif";
        /// <summary>
        /// .webp
        /// </summary>
        public const string ImageWebP = "image/webp;Image;webp";
        #endregion

        #region 文件类型:音频 FileType.Audio
        /// <summary>
        /// .aac
        /// </summary>
        public const string AudioAAC = "audio/aac;Audio;aac";
        /// <summary>
        /// .mid .midi
        /// </summary>
        public const string AudioMid = "audio/midi;Audio;mid";
        /// <summary>
        /// .mp3
        /// </summary>
        public const string AudioMp3 = "audio/mp3;Audio;mp3";
        /// <summary>
        /// .wav
        /// </summary>
        public const string AudioWav = "audio/wav;Audio;wav";
        /// <summary>
        /// .weba
        /// </summary>
        public const string AudioWebm = "audio/webm;Audio;weba";
        #endregion

        #region 文件类型：视频 FileType.Video
        /// <summary>
        /// .avi
        /// </summary>
        public const string VideoAVI = "video/x-msvideo;Video;avi";
        /// <summary>
        /// .mpeg
        /// </summary>
        public const string VideoMpeg = "video/mpeg;Video;mpeg";
        /// <summary>
        /// .webm
        /// </summary>
        public const string VideoWebm = "video/webm;Video;webm";
        /// <summary>
        /// mp4
        /// </summary>
        public const string VideoMp4 = "video/mp4;Video;mp4";
        /// <summary>
        /// .ogv
        /// </summary>
        public const string VideoOgv = "video/ogg;Video;ogv";
        #endregion

        #region 文件类型:文本文件 FileType.TextFile
        /// <summary>
        /// .json
        /// </summary>
        public const string ApplicationJson = "application/json;TextFile;json";
        /// <summary>
        /// .pdf
        /// </summary>
        public const string ApplicationPdf = "application/pdf;TextFile;pdf";
        /// <summary>
        /// xml
        /// </summary>
        public const string ApplicationRssXml = "application/rss+xml;TextFile;xml";
        /// <summary>
        /// .doc .docx
        /// </summary>
        public const string ApplicationMsWord = "application/msword;TextFile;doc";
        /// <summary>
        /// ppt pptx
        /// </summary>
        public const string ApplicationMsPPT = "application/vnd.ms-powerpoint;TextFile;ppt";
        /// <summary>
        /// .xls .xlsx Microsoft Excel (OpenXML)
        /// </summary>
        public const string ApplicationMsExcel = "application/vnd.ms-excel;TextFile;xls";
        /// <summary>
        /// .odp OpenDocument 
        /// </summary>
        public const string ApplicationOpenDocumentPPT = "application/vnd.oasis.opendocument.presentation;TextFile;odp";
        /// <summary>
        /// .ods
        /// </summary>
        public const string ApplicationOpenDocumentXls = "application/vnd.oasis.opendocument.spreadsheet;TextFile;ods";
        /// <summary>
        /// .odt
        /// </summary>
        public const string ApplicationOpenDocumentDoc = "application/vnd.oasis.opendocument.text;TextFile;odt";
        /// <summary>
        /// .wps
        /// </summary>
        public const string ApplicationWpsText = "application/wpsdoc;TextFile;wps";
        /// <summary>
        /// .wpt
        /// </summary>
        public const string ApplicationWpsPPT = "application/wpsppt;TextFile;wpt";
        /// <summary>
        /// .et
        /// </summary>
        public const string ApplicationWpsExcel = "application/wpsexcel;TextFile;et";
        /// <summary>
        /// .rtf
        /// </summary>
        public const string ApplicationRtf = "application/rtf;TextFile;rtf";
        /// <summary>
        /// .swf flash
        /// </summary>
        public const string ApplicationFlash = "application/x-shockwave-flash;TextFile;swf";
        /// <summary>
        /// .css .scss .less
        /// </summary>
        public const string TextCss = "text/css;TextFile;css";

        /// <summary>
        /// csv
        /// </summary>
        public const string TextCsv = "text/csv;TextFile;csv";

        /// <summary>
        /// js
        /// </summary>
        public const string TextJavascript = "text/javascript;TextFile;js";

        /// <summary>
        /// Type txt
        /// </summary>
        public const string TextPlain = "text/plain;TextFile;txt";
        #endregion
        /// <summary>
        /// Type
        /// </summary>
        public const string ApplicationForceDownload = "application/force-download";

        /// <summary>
        /// Type
        /// </summary>
        public const string ApplicationOctetStream = "application/octet-stream";

        /// <summary>
        /// Type
        /// </summary>
        public const string ApplicationXWwwFormUrlencoded = "application/x-www-form-urlencoded";

        protected static void InitSupportFiles()
        {
            _supportUploadFile = new Dictionary<string, string>
            { 
                //Key: 文件扩展名
                //Value: example : "image/gif;Image;gif" 以分号分隔为三部分
                //  第一部分：文件MimeType
                //  第二部分：文件FileType
                //  第三部分 文件上传后默认保存的扩展名，如jpeg, jpg pjpeg 统一保存为jpg

                //Image
                { ".bmp",  ImageBmp },
                { ".gif",  ImageGif },
                { ".jpeg", ImageJpeg },
                { ".jpg",  ImageJpeg },
                { ".jfif", ImageJpeg },
                { ".pjpeg",ImageJpeg },
                { ".png",  ImagePng },
                { ".tif",  ImageTiff },
                { ".tiff", ImageTiff },
                //File
                { ".bz",   ApplicationBzip },
                { ".bz2",  ApplicationBzip2 },
                { ".rar",  ApplicationRar },
                { ".tar",  ApplicationTar },
                { ".zip",  ApplicationZip },
                { ".7z",   Application7Zip },
                
                //Audio
                { ".aac",   AudioAAC },
                { ".mid",   AudioMid },
                { ".midi",  AudioMid },
                { ".mp3",   AudioMp3 },
                { ".wav",   AudioWav },
                { ".weba",  AudioWebm },
                
                //Video
                { ".avi",  VideoAVI },
                { ".mpeg", VideoMpeg },
                { ".webm", VideoWebm },
                { ".mp4",  VideoMp4 },
                { ".ogv",  VideoOgv },
                //TextFile
                { ".json",  ApplicationJson },
                { ".pdf",   ApplicationPdf },
                { ".xml",   ApplicationRssXml },
                { ".doc",   ApplicationMsWord },
                { ".docx",  ApplicationMsWord },
                { ".ppt",   ApplicationMsPPT },
                { ".pptx",  ApplicationMsPPT },
                { ".xls",   ApplicationMsExcel },
                { ".xlsx",  ApplicationMsExcel },
                { ".odt",   ApplicationOpenDocumentDoc },
                { ".odp",   ApplicationOpenDocumentPPT },
                { ".ods",   ApplicationOpenDocumentXls },
                { ".wps",   ApplicationWpsText },
                { ".wpt",   ApplicationWpsPPT },
                { ".et",    ApplicationWpsExcel },
                { ".rtf",   ApplicationRtf },
                { ".swf",   ApplicationFlash },
                { ".css",   TextCss },
                { ".csv",   TextCsv },
                { ".js",    TextJavascript },
                { ".txt",   TextPlain },
            };
        }
        /// <summary>
        /// 根据上传文件扩展名查询是否为支持的上传文件
        /// </summary>
        /// <param name="fileExtension"></param>
        /// <returns></returns>
        public static bool IsSupportByFileExt(string fileExtension)
        {
            if (_supportUploadFile == null)
                InitSupportFiles();
            return _supportUploadFile?.ContainsKey(fileExtension.ToLower()) ?? false;
        }
        /// <summary>
        /// 根据上传文件扩展名查询待存储文件的MimeType
        /// </summary>
        /// <param name="fileExtension"></param>
        /// <returns>File Mimetype</returns>
        public static string GetSupportFileMimetypeByFileExt(string fileExtension)
        {
            if (string.IsNullOrEmpty(fileExtension)) throw new ArgumentNullException(nameof(fileExtension));
            if (!fileExtension.StartsWith('.')) fileExtension = "." + fileExtension.ToLower().Trim();
            if (!IsSupportByFileExt(fileExtension)) throw new NowaException($"系统限制，{fileExtension}格式文件不允许上传");
            string fileValue;
            _supportUploadFile.TryGetValue(fileExtension, out fileValue);
            string[] values = fileValue.Split(';');
            if (values.Length < 3) throw new NowaException($"Bug Report: {fileExtension} 数据维护不完善");
            return values[0];
        }

        /// <summary>
        /// 根据文件MimeType(数据库存储)查询默认保存文件的扩展名
        /// 用于从数据库获取文件对象刷新保存本地文件夹存储时
        /// </summary>
        /// <param name="mimetype"></param>
        /// <returns></returns>
        public static string GetSupportFileExtensionByMimeType(string mimetype)
        {
            if (string.IsNullOrEmpty(mimetype)) throw new ArgumentNullException(nameof(mimetype));
            if (_supportUploadFile == null) InitSupportFiles();
            string fileExtension = string.Empty;
            foreach (var value in _supportUploadFile.Values)
            {
                string[] values = value.Split(';');
                if (values.Length < 3) throw new NowaException($"Bug Report: {value} 数据维护不完善");
                if (mimetype.Trim().ToLower() != values[0])
                    continue;
                else
                {
                    fileExtension = values[2];
                    break;
                }
            }
            if (string.IsNullOrEmpty(fileExtension)) throw new NowaException($"{mimetype} is not support for the moment");
            return fileExtension;
        }
        /// <summary>
        /// 根据上传文件扩展名查询文件的存储类型 FileType
        /// 用于从数据库获取文件对象刷新保存本地文件夹存储时
        /// </summary>
        /// <param name="mimetype"></param>
        /// <returns></returns>
        public static FileType GetSupportFileTypeByFileExt(string fileExtension)
        {
            if (string.IsNullOrEmpty(fileExtension)) throw new ArgumentNullException(nameof(fileExtension));
            if (!fileExtension.StartsWith('.')) fileExtension = "." + fileExtension.ToLower().Trim();
            if (!IsSupportByFileExt(fileExtension)) throw new NowaException($"{fileExtension} File not support for the moment");
            string fileValue;
            _supportUploadFile.TryGetValue(fileExtension, out fileValue);
            string[] values = fileValue.Split(';');
            if (values.Length < 3) throw new NowaException($"Bug Report: {fileExtension} 数据维护不完善");
            FileType filetype = values[1].ToEnum<FileType>();
            return filetype;
        }
    }
}